package com.xyy.ec.pop.erp.hx.utils.http;


import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import okhttp3.Request.Builder;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.File;
import java.io.IOException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author: liubowen
 * @date: 2019-04-17 11:32
 * @description:
 */
@Slf4j
public class RedirectUtil {


    private static final Long READ_TIMEOUT = 5 * 60 * 1000L;
    public static final int CONNECT_TIMEOUT = 30000;
    public static final int READ_TIMEOUT_THREE_MINUTES = 3 * 60 * 1000;

    private static final MediaType JSON = MediaType.parse("application/json;charset=utf-8");
    private static final Logger logger = LoggerFactory.getLogger(RedirectUtil.class);
    private static OkHttpClient clientHttps;
    private static OkHttpClient clientHttp;

    static {
        X509TrustManager trustManager = new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
            }

            @Override
            public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
            }

            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }
        };
        TrustManager[] tm = {trustManager};
        SSLContext sslContext = null;

        try {
            sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, tm, new SecureRandom());

            CommonInterceptor commonInterceptor = new CommonInterceptor("key", "Secret");
            clientHttps = new OkHttpClient.Builder().sslSocketFactory(sslContext.getSocketFactory(), trustManager).addInterceptor(commonInterceptor).readTimeout(3, TimeUnit.MINUTES).connectTimeout(3, TimeUnit.MINUTES).writeTimeout(3, TimeUnit.MINUTES).build();
            clientHttp = new OkHttpClient.Builder().addInterceptor(commonInterceptor).readTimeout(3, TimeUnit.MINUTES).connectTimeout(3, TimeUnit.MINUTES).writeTimeout(3, TimeUnit.MINUTES).build();
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
    }


    public static String doGet(String url) {
        return doGet(url, null);
    }

    public static String doGetParam(String url, Map<String, Object> param) {
        if (!param.isEmpty()) {
            StringBuilder stringBuilder = new StringBuilder(url);
            stringBuilder.append("?");
            for (Map.Entry entry : param.entrySet()) {
                stringBuilder.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
            }
            url = stringBuilder.toString();
            url = url.substring(0, url.lastIndexOf("&"));
        }
        return doGet(url, null);
    }

    public static String doGet(String url, long readTimeout) {
        return doGet(url, null, readTimeout);
    }

    public static String doGet(String url, Map<String, String> headers) {
        return doGet(url, headers, READ_TIMEOUT);
    }

    public static String doGet(String url, Map<String, String> headers, long readTimeout) {
        try {
            OkHttpClient okHttpClient = null;
            if (url.startsWith("https")) {
                okHttpClient = clientHttps;
            } else {
                okHttpClient = clientHttp;
            }
            Builder builder = okHttpClientBuilder(url, headers);

            final Request request = builder.build();

            final Call call = okHttpClient.newCall(request);
            Response response = call.execute();
            ResponseBody body = response.body();
            String string = body.string();

            return string;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }


    public static String doGet(String url, Map<String, String> headers, Map<String, Object> param) {
        try {
            OkHttpClient okHttpClient = null;
            if (url.startsWith("https")) {
                okHttpClient = clientHttps;
            } else {
                okHttpClient = clientHttp;
            }
            Builder builder = okHttpClientBuilder(url, headers, param);

            final Request request = builder.build();

            final Call call = okHttpClient.newCall(request);
            Response response = call.execute();
            ResponseBody body = response.body();
            String string = body.string();

            return string;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String doPostByFrom(String url) {
        return doPostByFrom(url, null);
    }

    public static String doPostByFrom(String url, long readTimeout) {
        return doPostByFrom(url, null, readTimeout);
    }

    public static String doPostByFrom(String url, Map<String, String> params) {
        return doPostByFrom(url, null, params);
    }

    public static String doPostByFrom(String url, Map<String, String> params, long readTimeout) {
        return doPostByFrom(url, null, params, readTimeout);
    }

    public static String doPostByFrom(String url, Map<String, String> headers, Map<String, String> params) {
        return doPostByFrom(url, headers, params, READ_TIMEOUT);
    }

    public static String doPostByFrom(String url, Map<String, String> headers, Map<String, String> params, long readTimeout) {
        return doPostByFrom(url, headers, params, null, null, null, readTimeout);
    }

    public static String doPostByFrom(String url, Map<String, String> headers, Map<String, String> params, String fileName, File file, MediaType fileType, long readTimeout) {
        try {
            OkHttpClient okHttpClient = null;
            if (url.startsWith("https")) {
                okHttpClient = clientHttps;
            } else {
                okHttpClient = clientHttp;
            }

            Builder builder = okHttpClientBuilder(url, headers);

            if (params != null && params.size() > 0) {
                MultipartBody.Builder requestBody = new MultipartBody.Builder().setType(MultipartBody.FORM);
                for (Map.Entry<String, String> entry : params.entrySet()) {
                    requestBody.addFormDataPart(entry.getKey(), entry.getValue());
                }

                if (!StringUtils.isBlank(fileName) && file != null && fileType != null) {
                    RequestBody body = RequestBody.create(fileType, file);
                    String filename = file.getName();
                    // 参数分别为， 请求key ，文件名称 ， RequestBody
                    requestBody.addFormDataPart(fileName, filename, body);
                }

                builder.post(requestBody.build());
            }

            final Request request = builder.build();

            final Call call = okHttpClient.newCall(request);
            Response response = call.execute();
            if (!response.isSuccessful()) {
                logger.warn("post请求失败, url = {}, code = {}, errorMessage = {}", url, response.code(), response.message());
                return null;
            }

            ResponseBody body = response.body();
            String string = body.string();

            return string;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String doPostByJson(String url, String jsonString) {
        return doPostByJson(url, new HashMap<String, String>(), jsonString, READ_TIMEOUT);
    }

    public static String doPostByJson(String url, Map<String, String> headers, String jsonString, long readTimeout) {
        try {
            OkHttpClient okHttpClient = null;
            if (url.startsWith("https")) {
                okHttpClient = clientHttps;
            } else {
                okHttpClient = clientHttp;
            }
            Builder builder = okHttpClientBuilder(url, headers);

            if (!StringUtils.isBlank(jsonString)) {
                RequestBody requestBody = RequestBody.create(JSON, jsonString);
                builder.post(requestBody);
            }

            final Request request = builder.build();

            final Call call = okHttpClient.newCall(request);
            Response response = call.execute();
            if (!response.isSuccessful()) {
                logger.warn("post请求失败, url = {}, code = {}, errorMessage = {}", url, response.code(), response.message());
                return null;
            }
            ResponseBody body = response.body();
            String string = body.string();

            return string;
        } catch (IOException e) {
            logger.error("#doPostByJson执行post请求异常,url={},jsonString={}", url, jsonString, e);
        }
        return null;
    }

    private static Builder okHttpClientBuilder(String url, Map<String, String> headers) {
        Builder builder = new Builder();
        builder.url(url);
        if (headers != null && headers.size() > 0) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                builder.addHeader(entry.getKey(), entry.getValue());
            }
        }


        return builder;
    }

    private static Builder okHttpClientBuilder(String url, Map<String, String> headers, Map<String, Object> param) {
        Builder builder = new Builder();
        HttpUrl.Builder urlBuilder = HttpUrl.parse(url).newBuilder();
        if (headers != null && headers.size() > 0) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                builder.addHeader(entry.getKey(), entry.getValue());
            }
        }

        if (MapUtils.isNotEmpty(param)) {

            for (Map.Entry<String, Object> entry : param.entrySet()) {
                if (StringUtils.isEmpty(entry.getKey()) || entry.getValue() == null) {
                    continue;
                }
                urlBuilder.addQueryParameter(entry.getKey(), entry.getValue().toString());
            }
        }
        builder.url(urlBuilder.build());


        return builder;
    }
}